package com.ship.dispatch.service.impl;

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ship.common.business.service.impl.BaseServiceImpl;
import com.ship.common.core.enums.MessageTypeEnum;
import com.ship.common.core.enums.ModuleUrlEnum;
import com.ship.common.core.utils.DateUtils;
import com.ship.common.core.web.domain.JsonResult;
import com.ship.dispatch.bean.ConShipping;
import com.ship.dispatch.bean.SpArrangeSchemeDetail;
import com.ship.dispatch.bean.SpDispatchScheme;
import com.ship.dispatch.bean.SpDispatchSchemeExecute;
import com.ship.dispatch.bean.decisionAnalysis.SmShipRent;
import com.ship.dispatch.bo.ItemStatisticsSimpleBo;
import com.ship.dispatch.mapper.SpArrangeSchemeDetailMapper;
import com.ship.dispatch.mapper.SpDispatchSchemeExecuteMapper;
import com.ship.dispatch.mapper.SpDispatchSchemeMapper;
import com.ship.dispatch.model.Vo.SmShipRentAnalysisFormatVo;
import com.ship.dispatch.service.ConShippingService;
import com.ship.dispatch.service.SpArrangeSchemeDetailService;
import com.ship.dispatch.service.decisionAnalysis.SmShipRentService;
import com.ship.dispatch.util.CommonUtil;
import com.ship.dispatch.util.NumberFormatUtil;
import com.ship.dispatch.vo.report.ShapeUnifyVo;
import com.ship.dispatch.vo.report.StackedDiagramItemVo;
import com.ship.dispatch.vo.report.StackedDiagramVo;
import com.ship.system.api.RemoteMessageSendService;
import com.ship.system.api.domain.SysMessageSend;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author zhangyh
 * @description 针对表【sp_arrange(货船排布)】的数据库操作Service实现
 * @createDate 2023-11-03 10:17:22
 */
@Service
public class SpArrangeSchemeDetailServiceImpl extends BaseServiceImpl<SpArrangeSchemeDetailMapper, SpArrangeSchemeDetail>
        implements SpArrangeSchemeDetailService {


    private static String[] RENT_SHIP_TYPE = new String[]{"138-150k ST","155-165k TFDE","174k 2-Stroke/MEGI/XDF"};

    @Autowired
    private ConShippingService conShippingService;

    @Resource
    private SpDispatchSchemeMapper spDispatchSchemeMapper;

    @Resource
    private SpDispatchSchemeExecuteMapper spDispatchSchemeExecuteMapper;

    @Autowired
    private SmShipRentService smShipRentService;

    @Resource
    private RemoteMessageSendService remoteMessageSendService;

    @Override
    public JSONObject dispatchArrangeCount(ItemStatisticsSimpleBo bo) {
        Long count = this.baseMapper.selectCount(
                new LambdaQueryWrapper<SpArrangeSchemeDetail>()
                        .gt(bo.getStartTime() != null,SpArrangeSchemeDetail::getExpectedLoadingDate,bo.getStartTime())
                        .lt(bo.getEndTime() != null,SpArrangeSchemeDetail::getExpectedLoadingDate,bo.getEndTime())
        );
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("totalNum", count);
        return jsonObject;
    }

    @Override
    public JSONObject yearDispatchArrangePieChart(ItemStatisticsSimpleBo bo) {
        List<SpArrangeSchemeDetail> detailList = this.baseMapper.selectList(
                new LambdaQueryWrapper<SpArrangeSchemeDetail>()
                        .gt(bo.getStartTime() != null,SpArrangeSchemeDetail::getExpectedLoadingDate,bo.getStartTime())
                        .lt(bo.getEndTime() != null,SpArrangeSchemeDetail::getExpectedLoadingDate,bo.getEndTime())
        );
        JSONObject jsonObject = new JSONObject();
        if(detailList.size() == 0){
            jsonObject.put("dataList", detailList);
            return jsonObject;
        }
        detailList = detailList.stream().sorted(Comparator.comparing(SpArrangeSchemeDetail::getPlanYear)).collect(Collectors.toList());
        Map<Integer,List<SpArrangeSchemeDetail>> yearMap = detailList.stream().collect(Collectors.groupingBy(SpArrangeSchemeDetail::getPlanYear));

        List<ShapeUnifyVo> shapeUnifyVos = new ArrayList<>();
        for (Integer integer : yearMap.keySet()) {
            ShapeUnifyVo unifyVo = new ShapeUnifyVo();
            unifyVo.setKey(String.valueOf(integer));
            unifyVo.setValue(String.valueOf(yearMap.get(integer).size()));
            shapeUnifyVos.add(unifyVo);
        }
        jsonObject.put("dataList", shapeUnifyVos);
        return jsonObject;
    }

    @Override
    public JSONObject yearDispatchArrangeHistogram(ItemStatisticsSimpleBo bo) {
        List<SpArrangeSchemeDetail> detailList = this.baseMapper.selectList(
                new LambdaQueryWrapper<SpArrangeSchemeDetail>()
                        .gt(bo.getStartTime() != null,SpArrangeSchemeDetail::getExpectedLoadingDate,bo.getStartTime())
                        .lt(bo.getEndTime() != null,SpArrangeSchemeDetail::getExpectedLoadingDate,bo.getEndTime())
        );
        JSONObject jsonObject = new JSONObject();
        if(detailList.size() == 0){
            jsonObject.put("dataList", detailList);
            return jsonObject;
        }
        detailList = detailList.stream().sorted(Comparator.comparing(SpArrangeSchemeDetail::getPlanYear)).collect(Collectors.toList());
        Map<Integer,List<SpArrangeSchemeDetail>> yearMap = detailList.stream().collect(Collectors.groupingBy(SpArrangeSchemeDetail::getPlanYear));

        List<ShapeUnifyVo> shapeUnifyVos = new ArrayList<>();
        for (Integer integer : yearMap.keySet()) {
            ShapeUnifyVo unifyVo = new ShapeUnifyVo();
            unifyVo.setKey(String.valueOf(integer));
            unifyVo.setValue(String.valueOf(yearMap.get(integer).size()));
            shapeUnifyVos.add(unifyVo);
        }
        jsonObject.put("dataList", shapeUnifyVos);
        return jsonObject;
    }

    @Override
    public JSONObject yearDispatchArrangeBuyCount(ItemStatisticsSimpleBo bo) {
        if(bo.getStartTime() == null || bo.getEndTime() == null){
            //没有传入时间则默认查询近一年的
            bo.setEndTime(new Date());
            bo.setStartTime(DateUtil.offsetMonth(new Date(),-12));
        }
        JSONObject jsonObject = new JSONObject();
        List<SpArrangeSchemeDetail> detailList = this.baseMapper.selectList(
                new LambdaQueryWrapper<SpArrangeSchemeDetail>()
                        .gt(bo.getStartTime() != null,SpArrangeSchemeDetail::getExpectedLoadingDate,bo.getStartTime())
                        .lt(bo.getEndTime() != null,SpArrangeSchemeDetail::getExpectedLoadingDate,bo.getEndTime())
        );
        if(detailList.size() == 0){
            jsonObject.put("totalNum", "0.00");
            return jsonObject;
        }
        BigDecimal sum = detailList.stream()
                .filter(obj -> obj.getSingleGoodsQuantity() != null)
                .map(SpArrangeSchemeDetail::getSingleGoodsQuantity)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        jsonObject.put("totalNum", NumberFormatUtil.numericFormatting(sum)+" MMBtu");
        return jsonObject;
    }

    @Override
    public JSONObject yearDispatchArrangeFinishCount(ItemStatisticsSimpleBo bo) {
        if(bo.getStartTime() == null || bo.getEndTime() == null){
            //没有传入时间则默认查询近一年的
            bo.setEndTime(new Date());
            bo.setStartTime(DateUtil.offsetMonth(new Date(),-12));
        }
        JSONObject jsonObject = new JSONObject();
        List<SpArrangeSchemeDetail> detailList = this.baseMapper.selectList(
                new LambdaQueryWrapper<SpArrangeSchemeDetail>()
                        .gt(bo.getStartTime() != null,SpArrangeSchemeDetail::getExpectedLoadingDate,bo.getStartTime())
                        .lt(bo.getEndTime() != null,SpArrangeSchemeDetail::getExpectedLoadingDate,bo.getEndTime())
                        .eq(SpArrangeSchemeDetail::getExecuteStatus,3)
        );
        if(detailList.size() == 0){
            jsonObject.put("totalNum", "0.00");
            return jsonObject;
        }
        BigDecimal sum = detailList.stream()
                .filter(obj -> obj.getRealityLoadingCapacity() != null)
                .map(SpArrangeSchemeDetail::getRealityLoadingCapacity)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        jsonObject.put("totalNum", NumberFormatUtil.numericFormatting(sum)+" MMBtu");
        return jsonObject;
    }

    @Override
    public JSONObject yearDispatchArrangeFinishRate(ItemStatisticsSimpleBo bo) {
        if(bo.getStartTime() == null || bo.getEndTime() == null){
            //没有传入时间则默认查询近一年的
            bo.setEndTime(new Date());
            bo.setStartTime(DateUtil.offsetMonth(new Date(),-12));
        }

        List<SpArrangeSchemeDetail> detailList = this.baseMapper.selectList(
                new LambdaQueryWrapper<SpArrangeSchemeDetail>()
                        .gt(bo.getStartTime() != null,SpArrangeSchemeDetail::getExpectedLoadingDate,bo.getStartTime())
                        .lt(bo.getEndTime() != null,SpArrangeSchemeDetail::getExpectedLoadingDate,bo.getEndTime())
        );
        JSONObject jsonObject = new JSONObject();
        if(detailList.size() == 0){
            jsonObject.put("totalNum", "0.00");
            return jsonObject;
        }
        BigDecimal buySum = detailList.stream()
                .filter(obj -> obj.getSingleGoodsQuantity() != null)
                .map(SpArrangeSchemeDetail::getSingleGoodsQuantity)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal finishSum = detailList.stream()
                .filter(obj -> obj.getRealityLoadingCapacity() != null && obj.getExecuteStatus() == 3)
                .map(SpArrangeSchemeDetail::getRealityLoadingCapacity)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        jsonObject.put("totalNum", finishSum.divide(buySum,2, RoundingMode.UP));
        return jsonObject;
    }

    @Override
    public JSONObject shipRentNowWestLineChart(ItemStatisticsSimpleBo bo) {
        return getRentMessage(bo,1);
    }

    /**
     * 获取租金信息
     * @param bo
     * @param type 1：现货西航线，2：现货东航线，3：中长期6个月，4：中长期12个月，5：中长期36个月
     * @return
     */
    public JSONObject getRentMessage(ItemStatisticsSimpleBo bo, int type){
        if(bo.getStartTime() == null || bo.getEndTime() == null){
            //没有传入时间则默认查询近一年的
            bo.setEndTime(new Date());
            bo.setStartTime(DateUtil.offsetMonth(new Date(),-12));
        }
        List<SmShipRent> detailList = smShipRentService.getBaseMapper().selectList(
                new LambdaQueryWrapper<SmShipRent>()
                        .ge(SmShipRent::getRentDate,bo.getStartTime())
                        .le(SmShipRent::getRentDate,bo.getEndTime())
        );
        JSONObject jsonObject = new JSONObject();
        if(detailList.size() == 0){
            jsonObject.put("dataList", detailList);
            return jsonObject;
        }
        List<StackedDiagramVo> stackedDiagramVos = new ArrayList<>();

        Calendar calendar = Calendar.getInstance();

        //判断是否跨年，如果跨年了需要将年份显示出来
        calendar.setTime(bo.getStartTime());
        int startYear = calendar.get(Calendar.YEAR);
        calendar.setTime(bo.getEndTime());
        int endYear = calendar.get(Calendar.YEAR);
        Boolean isDif = (startYear == endYear) ? false : true;

        for (SmShipRent smShipRent : detailList) {
            calendar.setTime(smShipRent.getRentDate());
            int year = calendar.get(Calendar.YEAR);
            smShipRent.setFormatDate(year+"-"+smShipRent.getRentWeek());
        }
        Map<String,List<SmShipRent>> rentMap = detailList.stream().collect(Collectors.groupingBy(SmShipRent::getFormatDate));

        for (String s : rentMap.keySet()) {
            List<SmShipRent> rentList = rentMap.get(s);
            SmShipRentAnalysisFormatVo formatVo = formatRentListAnalysis(rentList);

            calendar.setTime(rentList.get(0).getRentDate());
            int year = calendar.get(Calendar.YEAR);
            String month = String.valueOf(calendar.get(Calendar.MONTH) + 1);
            String day = String.valueOf(calendar.get(Calendar.DAY_OF_MONTH) + 1);
            if(month.length() < 2){
                month = ("0"+month);
            }
            if(day.length() < 2){
                day = ("0"+day);
            }
            String key = (month+"-"+day);
            if(isDif){
                key = (year+"-"+key);
            }
            formatVo.setKey(key);
            List<StackedDiagramItemVo> itemVos = new LinkedList<>();
            if(type == 1){
                for (int i = 0; i < RENT_SHIP_TYPE.length; i++) {
                    StackedDiagramItemVo itemVo1 = new StackedDiagramItemVo();
                    itemVo1.setKey(RENT_SHIP_TYPE[i]);
                    if(i == 0){
                        itemVo1.setValue(formatVo.getWest138().toString());
                    }else if(i == 1){
                        itemVo1.setValue(formatVo.getWest155().toString());
                    }else{
                        itemVo1.setValue(formatVo.getWest174().toString());
                    }
                    itemVos.add(itemVo1);
                }
            }else if(type == 2){
                for (int i = 0; i < RENT_SHIP_TYPE.length; i++) {
                    StackedDiagramItemVo itemVo1 = new StackedDiagramItemVo();
                    itemVo1.setKey(RENT_SHIP_TYPE[i]);
                    if(i == 0){
                        itemVo1.setValue(formatVo.getEast138().toString());
                    }else if(i == 1){
                        itemVo1.setValue(formatVo.getEast155().toString());
                    }else{
                        itemVo1.setValue(formatVo.getEast174().toString());
                    }
                    itemVos.add(itemVo1);
                }
            }else if(type == 3){
                for (int i = 0; i < RENT_SHIP_TYPE.length; i++) {
                    StackedDiagramItemVo itemVo1 = new StackedDiagramItemVo();
                    itemVo1.setKey(RENT_SHIP_TYPE[i]);
                    if(i == 0){
                        itemVo1.setValue(formatVo.getSix138().toString());
                    }else if(i == 1){
                        itemVo1.setValue(formatVo.getSix155().toString());
                    }else{
                        itemVo1.setValue(formatVo.getSix174().toString());
                    }
                    itemVos.add(itemVo1);
                }
            }else if(type == 4){
                for (int i = 0; i < RENT_SHIP_TYPE.length; i++) {
                    StackedDiagramItemVo itemVo1 = new StackedDiagramItemVo();
                    itemVo1.setKey(RENT_SHIP_TYPE[i]);
                    if(i == 0){
                        itemVo1.setValue(formatVo.getTwelve138().toString());
                    }else if(i == 1){
                        itemVo1.setValue(formatVo.getTwelve155().toString());
                    }else{
                        itemVo1.setValue(formatVo.getTwelve174().toString());
                    }
                    itemVos.add(itemVo1);
                }
            }else{
                for (int i = 0; i < RENT_SHIP_TYPE.length; i++) {
                    StackedDiagramItemVo itemVo1 = new StackedDiagramItemVo();
                    itemVo1.setKey(RENT_SHIP_TYPE[i]);
                    if(i == 0){
                        itemVo1.setValue(formatVo.getThirtySix138().toString());
                    }else if(i == 1){
                        itemVo1.setValue(formatVo.getThirtySix155().toString());
                    }else{
                        itemVo1.setValue(formatVo.getThirtySix174().toString());
                    }
                    itemVos.add(itemVo1);
                }
            }
            StackedDiagramVo diagramVo = new StackedDiagramVo();
            diagramVo.setName(key);
            diagramVo.setList(itemVos);
            stackedDiagramVos.add(diagramVo);
        }
        jsonObject.put("dataList", stackedDiagramVos);
        return jsonObject;
    }

    /**
     * 列表分析数据组装
     * @param rentList
     * @return
     */
    public SmShipRentAnalysisFormatVo formatRentListAnalysis(List<SmShipRent> rentList){
        SmShipRentAnalysisFormatVo resultData = new SmShipRentAnalysisFormatVo();
        BigDecimal east138 = BigDecimal.ZERO;
        BigDecimal east155 = BigDecimal.ZERO;
        BigDecimal east174 = BigDecimal.ZERO;
        BigDecimal west138 = BigDecimal.ZERO;
        BigDecimal west155 = BigDecimal.ZERO;
        BigDecimal west174 = BigDecimal.ZERO;
        BigDecimal six138 = BigDecimal.ZERO;
        BigDecimal six155 = BigDecimal.ZERO;
        BigDecimal six174 = BigDecimal.ZERO;
        BigDecimal twelve138 = BigDecimal.ZERO;
        BigDecimal twelve155 = BigDecimal.ZERO;
        BigDecimal twelve174 = BigDecimal.ZERO;
        BigDecimal thirtySix138 = BigDecimal.ZERO;
        BigDecimal thirtySix155 = BigDecimal.ZERO;
        BigDecimal thirtySix174 = BigDecimal.ZERO;

        for (SmShipRent smShipRent : rentList) {
            if(smShipRent.getVesselType().intValue() == 1){
                if(smShipRent.getSpotEast() != null){
                    east138 = east138.add(smShipRent.getSpotEast());
                }
                if(smShipRent.getSpotWest() != null){
                    west138 = west138.add(smShipRent.getSpotWest());
                }
                if(smShipRent.getRentSixMonth() != null){
                    six138 = six138.add(smShipRent.getRentSixMonth());
                }
                if(smShipRent.getRentTwelveMonth() != null){
                    twelve138 = twelve138.add(smShipRent.getRentTwelveMonth());
                }
                if(smShipRent.getRentThirtySixMonth() != null){
                    thirtySix138 = thirtySix138.add(smShipRent.getRentThirtySixMonth());
                }
            }else if(smShipRent.getVesselType().intValue() == 2){
                if(smShipRent.getSpotEast() != null){
                    east155 = east155.add(smShipRent.getSpotEast());
                }
                if(smShipRent.getSpotWest() != null){
                    west155 = west155.add(smShipRent.getSpotWest());
                }
                if(smShipRent.getRentSixMonth() != null){
                    six155 = six155.add(smShipRent.getRentSixMonth());
                }
                if(smShipRent.getRentTwelveMonth() != null){
                    twelve155 = twelve155.add(smShipRent.getRentTwelveMonth());
                }
                if(smShipRent.getRentThirtySixMonth() != null){
                    thirtySix155 = thirtySix155.add(smShipRent.getRentThirtySixMonth());
                }
            }else{
                if(smShipRent.getSpotEast() != null){
                    east174 = east174.add(smShipRent.getSpotEast());
                }
                if(smShipRent.getSpotWest() != null){
                    west174 = west174.add(smShipRent.getSpotWest());
                }
                if(smShipRent.getRentSixMonth() != null){
                    six174 = six174.add(smShipRent.getRentSixMonth());
                }
                if(smShipRent.getRentTwelveMonth() != null){
                    twelve174 = twelve174.add(smShipRent.getRentTwelveMonth());
                }
                if(smShipRent.getRentThirtySixMonth() != null){
                    thirtySix174 = thirtySix174.add(smShipRent.getRentThirtySixMonth());
                }
            }
        }

        //broker数量
        List<String> brokerList = rentList.stream().map(SmShipRent::getBroker).collect(Collectors.toList());
        brokerList = brokerList.stream().distinct().collect(Collectors.toList());
        BigDecimal brokerNum = new BigDecimal(String.valueOf(brokerList.size()));
        if(brokerNum.compareTo(BigDecimal.ZERO) == 0){
            brokerNum = new BigDecimal("1");
        }
        //指标单位是千
        brokerNum = brokerNum.multiply(new BigDecimal("1000"));
        resultData.setEast138(east138.divide(brokerNum,2,RoundingMode.UP));
        resultData.setEast155(east155.divide(brokerNum,2,RoundingMode.UP));
        resultData.setEast174(east174.divide(brokerNum,2,RoundingMode.UP));
        resultData.setWest138(west138.divide(brokerNum,2,RoundingMode.UP));
        resultData.setWest155(west155.divide(brokerNum,2,RoundingMode.UP));
        resultData.setWest174(west174.divide(brokerNum,2,RoundingMode.UP));
        resultData.setSix138(six138.divide(brokerNum,2,RoundingMode.UP));
        resultData.setSix155(six155.divide(brokerNum,2,RoundingMode.UP));
        resultData.setSix174(six174.divide(brokerNum,2,RoundingMode.UP));
        resultData.setTwelve138(twelve138.divide(brokerNum,2,RoundingMode.UP));
        resultData.setTwelve155(twelve155.divide(brokerNum,2,RoundingMode.UP));
        resultData.setTwelve174(twelve174.divide(brokerNum,2,RoundingMode.UP));
        resultData.setThirtySix138(thirtySix138.divide(brokerNum,2,RoundingMode.UP));
        resultData.setThirtySix155(thirtySix155.divide(brokerNum,2,RoundingMode.UP));
        resultData.setThirtySix174(thirtySix174.divide(brokerNum,2,RoundingMode.UP));
        return resultData;
    }

    @Override
    public JSONObject yearDispatchMonthFinishGoodsLineChart(ItemStatisticsSimpleBo bo) {
        if(bo.getStartTime() == null || bo.getEndTime() == null){
            //没有传入时间则默认查询近一年的
            bo.setEndTime(new Date());
            bo.setStartTime(DateUtil.offsetMonth(new Date(),-12));
        }
        List<SpDispatchSchemeExecute> detailList = spDispatchSchemeExecuteMapper.selectList(
                new LambdaQueryWrapper<SpDispatchSchemeExecute>()
                        .eq(SpDispatchSchemeExecute::getExecuteStatus,3)
                        .isNotNull(SpDispatchSchemeExecute::getFinishTime)
                        .gt(bo.getStartTime() != null,SpDispatchSchemeExecute::getFinishTime,bo.getStartTime())
                        .lt(bo.getEndTime() != null,SpDispatchSchemeExecute::getFinishTime,bo.getEndTime())
        );
        JSONObject jsonObject = new JSONObject();
        if(detailList.size() == 0){
            jsonObject.put("dataList", detailList);
            return jsonObject;
        }
        for (SpDispatchSchemeExecute spDispatchSchemeExecute : detailList) {
            spDispatchSchemeExecute.setFinishTimeMonth(DateUtils.parseDateToStr("yyyy-MM",spDispatchSchemeExecute.getFinishTime()));
        }
        Map<String,List<SpDispatchSchemeExecute>> detailMap = detailList.stream().collect(Collectors.groupingBy(SpDispatchSchemeExecute::getFinishTimeMonth));
        List<ShapeUnifyVo> shapeUnifyVos = new ArrayList<>();
        for (String date : detailMap.keySet()) {
            ShapeUnifyVo unifyVo = new ShapeUnifyVo();
            unifyVo.setKey(date);
            unifyVo.setValue(String.valueOf(detailMap.get(date).size()));
            shapeUnifyVos.add(unifyVo);
        }
        jsonObject.put("dataList", shapeUnifyVos);
        return jsonObject;
    }

    @Override
    public JSONObject yearDispatchMonthFinishGoodsHistogram(ItemStatisticsSimpleBo bo) {
        if(bo.getStartTime() == null || bo.getEndTime() == null){
            //没有传入时间则默认查询近一年的
            bo.setEndTime(new Date());
            bo.setStartTime(DateUtil.offsetMonth(new Date(),-12));
        }
        List<SpDispatchSchemeExecute> detailList = spDispatchSchemeExecuteMapper.selectList(
                new LambdaQueryWrapper<SpDispatchSchemeExecute>()
                        .eq(SpDispatchSchemeExecute::getExecuteStatus,3)
                        .isNotNull(SpDispatchSchemeExecute::getFinishTime)
                        .gt(bo.getStartTime() != null,SpDispatchSchemeExecute::getFinishTime,bo.getStartTime())
                        .lt(bo.getEndTime() != null,SpDispatchSchemeExecute::getFinishTime,bo.getEndTime())
        );
        JSONObject jsonObject = new JSONObject();
        if(detailList.size() == 0){
            jsonObject.put("dataList", detailList);
            return jsonObject;
        }
        for (SpDispatchSchemeExecute spDispatchSchemeExecute : detailList) {
            spDispatchSchemeExecute.setFinishTimeMonth(DateUtils.parseDateToStr("yyyy-MM",spDispatchSchemeExecute.getFinishTime()));
        }
        Map<String,List<SpDispatchSchemeExecute>> detailMap = detailList.stream().collect(Collectors.groupingBy(SpDispatchSchemeExecute::getFinishTimeMonth));
        List<ShapeUnifyVo> shapeUnifyVos = new ArrayList<>();
        for (String date : detailMap.keySet()) {
            ShapeUnifyVo unifyVo = new ShapeUnifyVo();
            unifyVo.setKey(date);
            unifyVo.setValue(String.valueOf(detailMap.get(date).size()));
            shapeUnifyVos.add(unifyVo);
        }
        jsonObject.put("dataList", shapeUnifyVos);
        return jsonObject;
    }

    @Override
    public JSONObject yearDispatchToExecuteGoodsCount(ItemStatisticsSimpleBo bo) {
        Long dataCount = this.baseMapper.selectCount(
                new LambdaQueryWrapper<SpArrangeSchemeDetail>()
                        .eq(SpArrangeSchemeDetail::getExecuteStatus,1)
                        .gt(bo.getStartTime() != null,SpArrangeSchemeDetail::getExpectedLoadingDate,bo.getStartTime())
                        .lt(bo.getEndTime() != null,SpArrangeSchemeDetail::getExpectedLoadingDate,bo.getEndTime())
        );
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("totalNum", dataCount);
        return jsonObject;
    }

    @Override
    public JSONObject yearDispatchGoingGoodsCount(ItemStatisticsSimpleBo bo) {
        Long dataCount = this.baseMapper.selectCount(
                new LambdaQueryWrapper<SpArrangeSchemeDetail>()
                        .eq(SpArrangeSchemeDetail::getExecuteStatus,2)
                        .gt(bo.getStartTime() != null,SpArrangeSchemeDetail::getExpectedLoadingDate,bo.getStartTime())
                        .lt(bo.getEndTime() != null,SpArrangeSchemeDetail::getExpectedLoadingDate,bo.getEndTime())
        );
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("totalNum", dataCount);
        return jsonObject;
    }

    @Override
    public JSONObject yearDispatchFinishGoodsCount(ItemStatisticsSimpleBo bo) {
        Long dataCount = this.baseMapper.selectCount(
                new LambdaQueryWrapper<SpArrangeSchemeDetail>()
                        .eq(SpArrangeSchemeDetail::getExecuteStatus,3)
                        .gt(bo.getStartTime() != null,SpArrangeSchemeDetail::getExpectedLoadingDate,bo.getStartTime())
                        .lt(bo.getEndTime() != null,SpArrangeSchemeDetail::getExpectedLoadingDate,bo.getEndTime())
        );
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("totalNum", dataCount);
        return jsonObject;
    }

    @Override
    public JSONObject yearDispatchTradeGetStatistics(ItemStatisticsSimpleBo bo) {
        if(bo.getStartTime() == null || bo.getEndTime() == null){
            //没有传入时间则默认查询近一年的
            bo.setEndTime(new Date());
            bo.setStartTime(DateUtil.offsetMonth(new Date(),-12));
        }
        List<SpDispatchScheme> detailList = spDispatchSchemeMapper.selectList(
                new LambdaQueryWrapper<SpDispatchScheme>()
                        .gt(bo.getStartTime() != null,SpDispatchScheme::getCreateDate,bo.getStartTime())
                        .lt(bo.getEndTime() != null,SpDispatchScheme::getCreateDate,bo.getEndTime())
        );
        JSONObject jsonObject = new JSONObject();
        if(detailList.size() == 0){
            jsonObject.put("dataList", detailList);
            return jsonObject;
        }
        Map<Date,List<SpDispatchScheme>> detailMap = detailList.stream().collect(Collectors.groupingBy(SpDispatchScheme::getCreateDate));
        List<ShapeUnifyVo> shapeUnifyVos = new ArrayList<>();
        for (Date date : detailMap.keySet()) {
            ShapeUnifyVo unifyVo = new ShapeUnifyVo();
            unifyVo.setKey(DateUtils.parseDateToStr("yyyy-MM-dd",date));
            List<SpDispatchScheme> schemeList = detailMap.get(date);
            BigDecimal trade = BigDecimal.ZERO;
            for (SpDispatchScheme dispatchScheme : schemeList) {
                if(dispatchScheme.getTrade() != null){
                    trade = trade.add(dispatchScheme.getTrade());
                }
            }
            unifyVo.setValue(String.valueOf(trade));
            shapeUnifyVos.add(unifyVo);
        }
        jsonObject.put("dataList", shapeUnifyVos);
        return jsonObject;
    }

    @Override
    public JSONObject yearDispatchShipDayLineChart(ItemStatisticsSimpleBo bo) {
        List<ConShipping> detailList = conShippingService.getBaseMapper().selectList(
                new LambdaQueryWrapper<ConShipping>()
                        .gt(bo.getStartTime() != null,ConShipping::getCreateDate,bo.getStartTime())
                        .lt(bo.getEndTime() != null,ConShipping::getCreateDate,bo.getEndTime())
        );
        JSONObject jsonObject = new JSONObject();
        if(detailList.size() == 0){
            jsonObject.put("dataList", detailList);
            return jsonObject;
        }
        int allCount = 0;
        int rentCount = 0;
        int innerCount = 0;
        for (ConShipping conShipping : detailList) {
            allCount ++;
            if(conShipping.getContractType() != null && 3 == conShipping.getContractType()){
                rentCount ++;
            }else{
                innerCount ++;
            }
        }
        List<ShapeUnifyVo> shapeUnifyVos = new ArrayList<>();
        ShapeUnifyVo allShape = new ShapeUnifyVo();
        allShape.setKey("当前可用船舶");
        allShape.setValue(String.valueOf(allCount));
        shapeUnifyVos.add(allShape);
        ShapeUnifyVo rentShape = new ShapeUnifyVo();
        rentShape.setKey("外租船舶");
        rentShape.setValue(String.valueOf(rentCount));
        shapeUnifyVos.add(rentShape);
        ShapeUnifyVo innerShape = new ShapeUnifyVo();
        innerShape.setKey("自有船舶");
        innerShape.setValue(String.valueOf(innerCount));
        shapeUnifyVos.add(innerShape);

        jsonObject.put("dataList", shapeUnifyVos);
        return jsonObject;
    }

    @Override
    public JSONObject yearDispatchShipHistogram(ItemStatisticsSimpleBo bo) {
        List<ConShipping> detailList = conShippingService.getBaseMapper().selectList(
                new LambdaQueryWrapper<ConShipping>()
                        .gt(bo.getStartTime() != null,ConShipping::getCreateDate,bo.getStartTime())
                        .lt(bo.getEndTime() != null,ConShipping::getCreateDate,bo.getEndTime())
        );
        JSONObject jsonObject = new JSONObject();
        if(detailList.size() == 0){
            jsonObject.put("dataList", detailList);
            return jsonObject;
        }
        int allCount = 0;
        int rentCount = 0;
        int innerCount = 0;
        for (ConShipping conShipping : detailList) {
            allCount ++;
            if(conShipping.getContractType() != null && 3 == conShipping.getContractType()){
                rentCount ++;
            }else{
                innerCount ++;
            }
        }
        List<ShapeUnifyVo> shapeUnifyVos = new ArrayList<>();
        ShapeUnifyVo allShape = new ShapeUnifyVo();
        allShape.setKey("当前可用船舶");
        allShape.setValue(String.valueOf(allCount));
        shapeUnifyVos.add(allShape);
        ShapeUnifyVo rentShape = new ShapeUnifyVo();
        rentShape.setKey("外租船舶");
        rentShape.setValue(String.valueOf(rentCount));
        shapeUnifyVos.add(rentShape);
        ShapeUnifyVo innerShape = new ShapeUnifyVo();
        innerShape.setKey("自有船舶");
        innerShape.setValue(String.valueOf(innerCount));
        shapeUnifyVos.add(innerShape);

        jsonObject.put("dataList", shapeUnifyVos);
        return jsonObject;
    }

    @Override
    public JSONObject yearDispatchShipStatisticsPieChart(ItemStatisticsSimpleBo bo) {
        List<ConShipping> detailList = conShippingService.getBaseMapper().selectList(
                new LambdaQueryWrapper<ConShipping>()
                        .gt(bo.getStartTime() != null,ConShipping::getCreateDate,bo.getStartTime())
                        .lt(bo.getEndTime() != null,ConShipping::getCreateDate,bo.getEndTime())
        );
        JSONObject jsonObject = new JSONObject();
        if(detailList.size() == 0){
            jsonObject.put("dataList", detailList);
            return jsonObject;
        }
        int allCount = 0;
        int rentCount = 0;
        int innerCount = 0;
        for (ConShipping conShipping : detailList) {
            allCount ++;
            if(conShipping.getContractType() != null && 3 == conShipping.getContractType()){
                rentCount ++;
            }else{
                innerCount ++;
            }
        }
        List<ShapeUnifyVo> shapeUnifyVos = new ArrayList<>();
        ShapeUnifyVo allShape = new ShapeUnifyVo();
        allShape.setKey("当前可用船舶");
        allShape.setValue(String.valueOf(allCount));
        shapeUnifyVos.add(allShape);
        ShapeUnifyVo rentShape = new ShapeUnifyVo();
        rentShape.setKey("外租船舶");
        rentShape.setValue(String.valueOf(rentCount));
        shapeUnifyVos.add(rentShape);
        ShapeUnifyVo innerShape = new ShapeUnifyVo();
        innerShape.setKey("自有船舶");
        innerShape.setValue(String.valueOf(innerCount));
        shapeUnifyVos.add(innerShape);

        jsonObject.put("dataList", shapeUnifyVos);
        return jsonObject;
    }

    @Override
    public JSONObject yearDispatchShipStatisticsHistogram(ItemStatisticsSimpleBo bo) {
        List<ConShipping> detailList = conShippingService.getBaseMapper().selectList(
                new LambdaQueryWrapper<ConShipping>()
                        .gt(bo.getStartTime() != null,ConShipping::getCreateDate,bo.getStartTime())
                        .lt(bo.getEndTime() != null,ConShipping::getCreateDate,bo.getEndTime())
        );
        JSONObject jsonObject = new JSONObject();
        if(detailList.size() == 0){
            jsonObject.put("dataList", detailList);
            return jsonObject;
        }
        int allCount = 0;
        int rentCount = 0;
        int innerCount = 0;
        for (ConShipping conShipping : detailList) {
            allCount ++;
            if(conShipping.getContractType() != null && 3 == conShipping.getContractType()){
                rentCount ++;
            }else{
                innerCount ++;
            }
        }
        List<ShapeUnifyVo> shapeUnifyVos = new ArrayList<>();
        ShapeUnifyVo allShape = new ShapeUnifyVo();
        allShape.setKey("当前可用船舶");
        allShape.setValue(String.valueOf(allCount));
        shapeUnifyVos.add(allShape);
        ShapeUnifyVo rentShape = new ShapeUnifyVo();
        rentShape.setKey("外租船舶");
        rentShape.setValue(String.valueOf(rentCount));
        shapeUnifyVos.add(rentShape);
        ShapeUnifyVo innerShape = new ShapeUnifyVo();
        innerShape.setKey("自有船舶");
        innerShape.setValue(String.valueOf(innerCount));
        shapeUnifyVos.add(innerShape);

        jsonObject.put("dataList", shapeUnifyVos);
        return jsonObject;
    }

    @Override
    public JSONObject shipRentNowEastLineChart(ItemStatisticsSimpleBo bo) {
        return getRentMessage(bo,2);
    }

    @Override
    public JSONObject shipRentSixLineChart(ItemStatisticsSimpleBo bo) {
        return getRentMessage(bo,3);
    }

    @Override
    public JSONObject shipRentTwelveLineChart(ItemStatisticsSimpleBo bo) {
        return getRentMessage(bo,4);
    }

    @Override
    public JSONObject shipRentThirtySixLineChart(ItemStatisticsSimpleBo bo) {
        return getRentMessage(bo,5);
    }

    @Override
    public void dispatchExpireMessageSend() {
        //巴拿马运河预定提醒
        List<SpArrangeSchemeDetail> schemeDetailList = this.baseMapper.selectList(
                new LambdaQueryWrapper<SpArrangeSchemeDetail>()
                        .le(SpArrangeSchemeDetail::getExpectedLoadingDate,new Date())
        );
        List<SysMessageSend> messageSendList = new LinkedList<>();
        if(schemeDetailList.size() > 0){
            for (SpArrangeSchemeDetail schemeDetail : schemeDetailList) {
                if(schemeDetail.getShipRoute().indexOf("1") > -1){
                    //巴拿马运河预定提醒
                    SysMessageSend messageSend = new SysMessageSend();
                    messageSend.setMessageUrl(ModuleUrlEnum.CHPB.getUrl());
                    messageSend.setMessageType(MessageTypeEnum.MESSAGE_TYPE_18.getCode());
                    messageSend.setContentParam(new String[]{schemeDetail.getVoyageNo()
                            , DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss",schemeDetail.getExpectedLoadingDate())});
                    messageSend.setCompareType(5);
                    messageSend.setCompareValue(com.ship.common.core.utils.DateUtil.getDateDays(new Date(),schemeDetail.getExpectedLoadingDate(),1).intValue());
                    messageSendList.add(messageSend);
                }
                if(schemeDetail.getShipRoute().indexOf("2") > -1){
                    //苏伊士运河预定提醒
                    SysMessageSend messageSend = new SysMessageSend();
                    messageSend.setMessageUrl(ModuleUrlEnum.CHPB.getUrl());
                    messageSend.setMessageType(MessageTypeEnum.MESSAGE_TYPE_19.getCode());
                    messageSend.setContentParam(new String[]{schemeDetail.getVoyageNo()
                            , DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss",schemeDetail.getExpectedLoadingDate())});
                    messageSend.setCompareType(5);
                    messageSend.setCompareValue(com.ship.common.core.utils.DateUtil.getDateDays(new Date(),schemeDetail.getExpectedLoadingDate(),1).intValue());
                    messageSendList.add(messageSend);
                }

                //装载时间确认
                SysMessageSend messageSend = new SysMessageSend();
                messageSend.setMessageUrl(ModuleUrlEnum.CHPB.getUrl());
                messageSend.setMessageType(MessageTypeEnum.MESSAGE_TYPE_20.getCode());
                messageSend.setContentParam(new String[]{schemeDetail.getVoyageNo()
                        , DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss",schemeDetail.getExpectedLoadingDate())});
                messageSend.setCompareType(5);
                messageSend.setCompareValue(com.ship.common.core.utils.DateUtil.getDateDays(new Date(),schemeDetail.getExpectedLoadingDate(),1).intValue());
                messageSendList.add(messageSend);
            }
        }
        if(messageSendList.size() == 0){
            return;
        }
        remoteMessageSendService.messageSendBatch(messageSendList);
    }
}




